<?php
/**
 * 此文件是CMSHead模板中使用的函数库 awen add 2012-11-02
 */
/**
 * volist name的函数
 * 用法：<volist name=":ch1('news','223,224,225,21', 6)" id="vo">
 * @param $modelName 强制指定模型名称 模型名称可映射CMSHEAD_KEY_ROUTER 默认Article
 * @param $SqlOrCids Sql语句或栏目IDs
 * @param $limit 条数 
 * @param $cache 缓存name:time or time
 * @return array 二维
 */
function ch1($modelName='Article', $SqlOrCids='', $limit='', $cache=''){	
	$args = func_get_args();
	if( $args[0]=='' || preg_match('/^(select.+from.*)|(\d+(,\d+)*)$/i', $args[0]) ){ //未强制指定模型名称		
		$modelName = 'Article';
		$SqlOrCids = $args[0];
		$limit = count($args)>1 ? $args[1] : '';
		$cache = count($args)>2 ? $args[2] : '';
	}else{
		$tmp = is_array(C('CMSHEAD_KEY_ROUTER')) ? C('CMSHEAD_KEY_ROUTER') : array();
		if( array_key_exists($modelName, $tmp) ){
			$modelName = $tmp[$modelName];
		}
		$modelName = ucfirst(strtolower($modelName));
	}
	//若有缓存数据，直接返回
	$objcache = array();
	if($cache){
		$arr = explode(':',$cache);
		$objcache[0] = is_numeric($arr[1]) ?  $arr[0] : (is_numeric($arr[0]) ? md5(serialize($args)) : $arr[0]); //名称
		$objcache[1] = NULL; //data 后面设置
		$objcache[2] = is_numeric($arr[1]) ? $arr[1] : (is_numeric($arr[0]) ? $arr[0] : 60); //时间
		if( $objcache[0] && $dataCache = S($objcache[0]) ){
			return $dataCache;
		}
	}
		
	$where = array();
	if(preg_match('/^select.+from[\s]+([^\s]+).*$/i',$SqlOrCids,$arr)){ //SQL语句
		$modelName = ucfirst(strtolower(str_replace(C('DB_PREFIX'),'',$arr[1])));
		$list = M('Node')->query($SqlOrCids);
	}elseif(preg_match('/^\d+(,\d+)*$/',$SqlOrCids)){ //栏目ids
		if($modelName == 'Category'){
			$where['classpid'] = array('in', explode(',', $SqlOrCids));
		}else{ //同一篇文章可以属于多个栏目 tid是逗号分隔的ids
			$tmp = explode(',', childClass($SqlOrCids,'id'));
			foreach($tmp as $id){
				$str .= ($str!='' ? ' or ' : '')."find_in_set($id,tid)";
			}
			if($str!='') $where['_string'] .= "($str)";
		}
		$model = M($modelName);
	}else{
		$model = M($modelName);
	}
	
	if($model){
		if($modelName=='Category'){
			$where['classstatus'] = 1;			
			$model->where($where)->order('classsort desc,classid asc');
		}else{
			$fields = $model->getDbFields();
			if(in_array('status', $fields)) $where['status'] = 1;
			if($where) $model->where($where);
			
			$params = array();
			if(in_array('sort', $fields)) $params[] = 'sort desc';
			if(in_array('add_time', $fields)) $params[] = 'add_time desc';
			$pk = in_array('id', $fields) ? 'id' : $model->getPk();
			$params[] = $pk.' desc';
			if($params) $model->order(implode(',',$params));
			//同时取栏目表字段
			if(in_array('tid', $fields)){ 
				$model->join(C('DB_PREFIX').'category ON '.C('DB_PREFIX').'category.classid = '.C('DB_PREFIX').strtolower($modelName).'.tid');
			}
		}		
		if($limit!='') $model->limit($limit);
//		return $model->buildSql();
		$list = $model->select();
	}
	
	//获取信息的url
	$need_url = !in_array('url', $fields) && !in_array('classurl', $fields);
	if( $need_url ){
		//取得当前控制器类名
		$arr = chapp(); $action = $arr['action'][0];
		if( class_exists($action) && method_exists($action, 'changurl') ){
			foreach($list as $key=>$rs){
				if($modelName == 'Category'){
					$rs['classmethod']=$rs['classmodule'].'/index';
				}else	
					$rs['method']=$modelName.'/view';
				$list[$key] = @call_user_func_array( array($action, 'changurl'), array($rs) );
			}
		}
	}
	
	if(is_array($objcache) && $objcache){ //缓存
		$objcache[1] = $list;
		call_user_func_array('S', $objcache); unset($objcache);
	}
	return $list;
}

/**
 * 连贯操作，参数个数次序随意，函数后面的多个参数用:分隔，一个参数里面的多个值用,号，第一个参数必须是模型名，或者栏目IDS（但如果省略则是Article）
 * 用法：ch2('article','field:id,img,title,rewrite','where:status=1 and img!=""','order:sort DESC,add_time DESC','limit:0,1','cache:Index_SlideNews:3')
 * 或者：S('Index_SlideNews');
 * 或者：ch2('limit:2','order:id desc');
 * 模型名称（可省略）或连贯操作的函数名都可映射CMSHEAD_KEY_ROUTER 
 * @return array 二维
 */
function ch2(){
	$existsKeys = $whereParams = $objcache = array();
	$modelKeys = array('table','where','order','field','limit','cache','distinct','join','group','page');
	$args = func_get_args();
	if($args){		
		foreach($args as $arg){
			$arr = explode(':', $arg);
			$tmp = is_array(C('CMSHEAD_KEY_ROUTER')) ? C('CMSHEAD_KEY_ROUTER') : array();
			if( array_key_exists($arr[0], $tmp) ){
				$modelKey = $tmp[$arr[0]];
			}else $modelKey = $arr[0];
			$existsKeys[] = $modelKey;
			
			//若有缓存数据，直接返回
			if($modelKey=='cache'){
				$objcache[0] = is_numeric($arr[2]) ?  $arr[1] : (is_numeric($arr[1]) ? md5(serialize($args)) : $arr[1]); //名称
				$objcache[1] = NULL; //data 后面设置
				$objcache[2] = is_numeric($arr[2]) ? $arr[2] : (is_numeric($arr[1]) ? $arr[1] : 60); //时间
				if( $objcache[0] && $dataCache = S($objcache[0]) ){
					return $dataCache;
				}
			}  
		}		
		
		if(preg_match('/^\d+(,\d+)*$/',$args[0])){ //栏目ids
			$tmp = explode(',',childClass($args[0],'id'));
			$modelName = M('Category')->where(array('classid'=>$tmp[0]))->limit(1)->getField('classmodule');
			//同一篇文章可以属于多个栏目 tid是逗号分隔的ids  2013-2-7
			//$whereParams['tid'] = array('in', $tmp);
			foreach($tmp as $id){
				$str .= ($str!='' ? ' or ' : '')."find_in_set($id,tid)";
			}
			if($str!='') $whereParams['_string'] .= "($str)";			
		}else{
			$tmp = is_array(C('CMSHEAD_KEY_ROUTER')) ? C('CMSHEAD_KEY_ROUTER') : array();
			if( array_key_exists($args[0], $tmp) ){
				$modelName = $tmp[$args[0]];
			}else $modelName = $args[0];
		}
	}
	if( preg_match('/^[a-z]\w+$/i',$modelName) ){ //判断模型合法性
		$array = M('Node')->cache('tables', 600)->query('show tables;');
		foreach($array as $arr){
			if( strtolower(C('DB_PREFIX').$modelName) == strtolower($arr['Tables_in_'.C('DB_NAME')]) ){
				$modelName = ucfirst(strtolower($modelName));
				$modelisOK = true;
				break;
			}
		}
	}
	if(!$modelisOK) $modelName = 'Article'; //默认模型
	$model = M($modelName);
	$fields = $model->getDbFields();	
	$havepage = in_array('page', $existsKeys);
	
	foreach($args as $arg){
		$arr = explode(':', $arg);
		if(($num = count($arr)) > 1 ){			
			$tmp = is_array(C('CMSHEAD_KEY_ROUTER')) ? C('CMSHEAD_KEY_ROUTER') : array();
			if( array_key_exists($arr[0], $tmp) ){
				$modelKey = $tmp[$arr[0]];
			}else $modelKey = $arr[0];		
			
			if( in_array($modelKey, $modelKeys) ){
				if($havepage){
					if($modelKey=='limit' or $modelKey=='cache'){
						unset($existsKeys[$modelKey]);
						continue;
					}
				}
				$params = trim(str_replace(array('&quot;','&#039;'), array('"',"'"), implode(':', array_slice($arr,1)) )); //去掉	$modelKey的其他	
//				echo $modelKey.' => '.$params.'<br>';					
				//解析参数中存在的变量
				if(preg_match_all('/([\'"] *\. *)(.*?)( *\. *[\'"])/', $params, $tmpArr)){
					for($k=0,$m=count($tmpArr[0]); $k<$m; $k++){
						$temp = NULL;
						@eval('$temp = '.$tmpArr[2][$k].';');
						if(!is_null($temp)) $params = str_replace($tmpArr[0][$k] , trim($tmpArr[1][$k],'.').$temp.trim($tmpArr[3][$k],'.') , $params);
					}
				}
				//自动加上URL重写值rewrite字段
				if(in_array('rewrite', $fields) && $modelKey=='field' && $params!='*'){ 
					if( !in_array('rewrite', explode(',', $params)) ){
						$params .= ',rewrite';
					}
				}
				//如果不是后台预览，则自动加上部分默认where条件，★where可能有多个★
				if($modelKey=='where'){
					if(substr($params,0,1)!='@'){ //其他直接call ch2传入的条件
						$whereParams['_string'] .= $whereParams['_string'] ? " and ($params)" : $params;
					}else{ //分页Sys:page传入的条件，序列化where:@...
						$params = unserialize(substr($params,1));
						if(is_array($params)){
							$whereParams = array_merge( $whereParams, $params );
						}else{
							$whereParams['_string'] .= $whereParams['_string'] ? " and ($params)" : $params;
						}
					}
				}				
				//自动加上默认排序字段
				if($modelKey=='order'){
					if(substr($params,-1)=='$'){//结束符号，不用再附加了
						$params = rtrim($params,'$');
					}else{
						if($params=='2'){ //最热
							$params = '';
							if(in_array('apv', $fields)) $params = 'apv desc,';
							if(in_array('sort', $fields) && false===strpos($params,'sort')) $params .= 'sort desc,';
						}elseif($params=='1'){ //最新
							 $params = '';
							 //if(in_array('id', $fields) && false===strpos($params,'id')) $params .= 'id desc,';
						}else{ //其他						
							if(in_array('sort', $fields) && false===strpos($params,'sort')) $params = 'sort desc,'.trim($params,',');
						}
						if(in_array('add_time', $fields) && false===strpos($params,'add_time')) $params = trim($params,',').',add_time desc,';
						$params = trim($params,',');
					}
				}				
				if($num>1) $params = explode(':', $params);
				if($modelKey=='page' && is_array($params)){
					$pageParams = $params;
				}
				if($modelKey!='where'){
					if(is_array($params)) @call_user_func_array( array($model, $modelKey), $params );
					else @call_user_func( array($model, $modelKey), $params );					
				}
			}
		}
	}

	//执行查询条件，加上默认条件
	if(!($_SESSION[C('USER_AUTH_KEY')] && $_GET['preview']==1)){ //非后台预览
		if(in_array('classstatus', $fields)) $whereParams['classstatus'] = 1;
		elseif(in_array('status', $fields)){
			if(in_array('tid', $fields)) $whereParams['classstatus'] = 1;
			$whereParams['status'] = 1;
		} 
	}
	$model->where($whereParams);
	
	//自动加上默认排序字段
	if(!in_array('order', $existsKeys)){
		$params = '';
		if(in_array('sort', $fields)) $params = 'sort desc,'.$params;
		if(in_array('add_time', $fields)) $params .= 'add_time desc,';
		$model->order(rtrim($params,','));
	}
	
	//同时取栏目表字段
	if($modelName!='Category' && in_array('tid', $fields)){
		$model->join(C('DB_PREFIX').'category ON '.C('DB_PREFIX').'category.classid = '.C('DB_PREFIX').strtolower($modelName).'.tid');
	}
	
	//最后，分页的处理
	if( in_array('page', $existsKeys) ){		 
		$sql = $model->buildSql();
		$sql = preg_replace('/^(select )(.+)$/i', '${1}SQL_CALC_FOUND_ROWS ${2}', trim($sql,'() ')); //为获取总条数做准备
		if(false!==stripos($sql, ' LIMIT ')){
			$tmpsql = preg_replace('/ LIMIT \d+(,\d+)? /i', ' limit 1',$sql);
			$tmp = $model->query($tmpsql);
		}else{
			$tmpsql .= ' limit 1';
			$tmp = $model->query($tmpsql);		
		}
		$tmp = $model->query('select FOUND_ROWS() as rowCount;');
		$rowCount = $tmp[0]['rowCount'];
		
		import('ORG.Util.Page');
		$pageSize = is_array($pageParams) ? $pageParams[0] : 20;
		$pageClass = new Page($rowCount, $pageSize);		
		$page = $pageClass->show();
		//此处始终有个 LIMIT 40,20而且改不过来，好奇怪，不得已用了个容错。		
		if(false!==stripos($sql, ' LIMIT ')){
			$sql = preg_replace('/ LIMIT \d+(,\d+)?/i', " LIMIT {$pageClass->firstRow},{$pageClass->listRows}",$sql);
			$list = $model->query($sql);
		}else{
			$sql .= " limit {$pageClass->firstRow},{$pageClass->listRows}";			
			$list = $model->query($sql);
		}
//		echo $sql;exit;
	}else{	
//		echo $model->buildSql();exit;
		$list = $model->select();
	}
	
	//获取信息的url
	$need_url = !in_array('url', $fields) && !in_array('classurl', $fields);
	if( $need_url ){
		//取得当前控制器类名
		$arr = chapp(); $action = $arr['action'][0];
		if( class_exists($action) && method_exists($action, 'changurl') ){
			foreach($list as $key=>$rs){
				if($modelName == 'Category'){
					$rs['classmethod']=$rs['classmodule'].'/index';
				}else	
					$rs['method']=$modelName.'/view';
				$list[$key] = @call_user_func_array( array($action, 'changurl'), array($rs) );
			}
		}
	}
	
	if(is_array($objcache) && $objcache){ //缓存
		$objcache[1] = $list;
		call_user_func_array('S', $objcache); unset($objcache);
	}
	return isset($page) ? array('list'=>$list, 'page'=>$page) : $list;
}
/**
 * 取得当前网址下的app信息
 * @return array action app vars
 */
function chapp(){
	//取得当前控制器类名
	$url = (0===strpos($_SERVER['REQUEST_URI'],__ROOT__)) ? substr($_SERVER['REQUEST_URI'], strlen(__ROOT__)) : $_SERVER['REQUEST_URI'];  //以前用的PATH_INFO，有缺陷	
	$rewrite = trim(urldecode($url),'/');	
	$rewrite = str_replace(__APP__.'/','',__ACTION__); 
	$rewrite = preg_replace('/[\/]+/','/',str_replace(array('?','&','='), '/', $rewrite));
	$exp = explode('/', $rewrite);
	$rs = M("Router")->where(array('rewrite'=>$exp[0]))->field('url')->find();
	if($rs){
		//把news/p/2 转成 article/index/id/224/p/2 附加参数
		for($i=1,$n=count($exp); $i<$n; $i++){
			if($exp[$i]!='') $rs['url'] .= '/'.$exp[$i];
		}
		//形如id/2/a/1/b/B/c/C的 参数转化为数组
		$exp = explode('/', $rs['url']);
	}
	$vars = array();
	for($i=2,$n=count($exp)-1; $i<$n; $i++){
		$vars[$exp[$i]]=$exp[$i+1];
		$i++;
	}
	$action = array(ucfirst(strtolower($exp[0])).'Action', strtolower($exp[1]));
	return array('action'=>$action, 'app'=>$exp, 'vars'=>$vars, 'url'=>$url);
}

/**
 * 动态生成缩略图或格式化图片输出
 * 调用方法：{$vo.img|chimg=500,500} {$vo.img|chimg='theory',500,500} {$vo.img|chimg}
 * @param $img
 * @param $modelName
 * @param $w
 * @param $h
 * @return thumb img full src
 */
function chimg($img,$modelName='article',$w=0,$h=0){
	$args = func_get_args();
	if(($n=count($args))<4){
		if($n==3 && !is_numeric($args[0]) && is_numeric($args[1]) && is_numeric($args[2])){			
			$img = $args[0]; $modelName = 'article'; 
			$w = $args[1]; $h = $args[2];
		}
	}
	$dirroot=$_SERVER['DOCUMENT_ROOT'].__ROOT__;
	$localpath = '/Public/Upload/'.strtolower($modelName).'/';
	if(!is_dir($dirroot.$localpath)){
		$tmp = C('CMSHEAD_KEY_ROUTER');
		$localpath = '/Public/Upload/'.strtolower($tmp[$modelName]).'/';
	}
	if($w>0 && $h>0){
		$thumbImg = strlen(dirname($img))>1 ? dirname($img).'/'.$w.'_'.$h.'_'.basename($img) : $w.'_'.$h.'_'.$img;		
		if(is_file($dirroot.$localpath.$thumbImg)){
			$thumbImg = __ROOT__.$localpath.$thumbImg;
		}elseif(is_file($dirroot.$localpath.$img)){			
			import('ORG.Util.Image');
			Image::thumb($dirroot.$localpath.$img, $dirroot.$localpath.$thumbImg, '', $w, $h);			
			$thumbImg = __ROOT__.$localpath.$thumbImg;
		}else{
			$thumbImg = $img;
		}
	}else{
		$thumbImg = is_file($dirroot.$localpath.$img) ? __ROOT__.$localpath.$img : $img;
	}
	return empty($thumbImg) ? __ROOT__.'/Public/Images/noimg.jpg' : $thumbImg;
}

/**
 * 输出视频
 * @param $file
 * @param $width
 * @param $height
 * @return html
 */
function chvideo($file,$width=660,$height=450){
	if(empty($file)) return '没有视频文件';
	$local = (false===stripos(str_ireplace(C('SITE_URL'),'',$file),'http'));	
	$flash = preg_match('/\.(swf|flv)/i', $file);
	$file = chimg($file, 'video');
	if($flash){
		if($local){
			$str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="'.$width.'" height="380">
                        <param name="movie" value="__PUBLIC__/Plugin/Flvplayer/Flvplayer.swf">
                        <param name="quality" value="high">
                        <param name="wmode" value="transparent">
                        <param name="allowFullScreen" value="true" />
                        <param name="FlashVars" value="vcastr_file='.$file.'&IsAutoPlay=0" />	
                        <embed src="__PUBLIC__/Plugin/Flvplayer/Flvplayer.swf" allowFullScreen="true" FlashVars="vcastr_file='.$file.'&IsAutoPlay=0" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="'.$width.'" height="'.$height.'" wmode="transparent"></embed>
                        </object>';
		}else{
			$str = '<embed src="'.$file.'" allowFullScreen="true" quality="high" width="'.$width.'" height="'.$height.'" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash"></embed>';
		}
	}else{
		$str = '<EMBED type="application/x-mplayer2" pluginspage="http://www.microsoft.com/Windows/Downloads/Contents/MediaPlayer/" width='.$width.' height='.$height.' src="'.$file.'" autorewind="true" showdisplay="false" showstatusbar="true" showcontrols="true" autostart="true" filename="'.$file.'"></EMBED>';
	}
	return $str;
}

/**
 * 格式化，去掉html代码，可带截取
 * @param $str
 * @param $length
 * @return string or array's string
 */
function encode($str, $length=0){
	if(is_array($str)){
		foreach($str as $k => $v) $data[$k] = encode($v, $length);
		return $data;
	}
	
	if(!empty($length)){
		$estr = htmlspecialchars( preg_replace('/(&[a-zA-Z]{2,5};)|(\s)/','',strip_tags(str_replace('[CHPAGE]','',$str))) );
		if($length<0) return $estr;
		return msubstr($estr,0,$length);
	}
	return htmlspecialchars( trim(strip_tags($str)) );
}
//截取字符串，msubstr的别名
function cutstr($str,$length,$suffix=0){
	if(is_array($str)){
		foreach($str as $k => $v) $data[$k] = cutstr($v, $length, $suffix);
		return $data;
	}
	if($length>0) $str = str_replace('[CHPAGE]','',$str);
	return msubstr($str, 0, $length, 'utf-8', $suffix);
}
//模板中参数的过滤，保留html代码，通常用在ch2,ch1中接收参数时候
function safe($value,$type='str'){
	if(is_array($value)){
		foreach($value as $k => $v) $data[$k] = safe($v,$type);
		return $data;
	}
	
	switch($type){
		case 'str':
			return str_replace(array('"',"'",'%','[CHPAGE]'), array('&quot;','&#039;','％',''),htmlspecialchars(trim($value)));
			break;
		case 'int':
			return is_numeric($value) ? $value : -1;
			break;
		case 'date':
		case 'time':
			return is_date($value) ? $value : '';
			break;
		default:
			return $value;
			break;
	}
}

/**
 * 检测当前模块自定义的隐射的某个字段的名称，比如用户可能把title改成biaoti，这里根据title返回biaoti
 * @param $modelName 模型名称
 * @param $fromFieldName 隐射的字段如title
 * @return 修改后的字段如biaoti
 */
function trueMapField($modelName, $fromFieldName='title'){
	static $truefield = '';
	if($truefield) return $truefield;
    $fieldsmap = M('model_fieldnotes')->where(array('ename'=>$modelName))->getField('fieldsmap');
    if($fieldsmap && is_array($fieldsmap=unserialize($fieldsmap))){
    	foreach($fieldsmap as $field=>$val){
    		if($val['search_names']==$fromFieldName){
    			return $truefield = $field;
    		}
    	}
    }
    return $fromFieldName;
   
}

/**  
 * 2013-2-7 获取指定栏目的所有子栏目（包括自己）
 * @param $cids 指定的栏目ids，多个逗号分隔
 * @param $fields 要获取的字段信息，多个逗号分隔，如果只获取classid，则指定成classid或id
 * @return string ids或array list
 */
function childClass($cids,$fields='*'){
	if(!is_array($cids)) $cids = explode(',',$cids);
	$model = M('Category')->where( array('classid'=>array('in', $cids)) );
	$list = $model->field('classchildids')->select();
	if($list){
		foreach($list as $rs){
			$childClassIds .= ($childClassIds!='' ? ',':''). $rs['classchildids'];
		}
		if($fields=='classid' || $fields=='id') return $childClassIds;
	}else{
		return $cids;
	}	
	$model = M('Category')->where( array('classid'=>array('in', $childClassIds)) );
	if($fields!='*') $model->field($fields);
	return $model->select();
}